#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

#include <cstring>
#define DEBUG_RORATE		(7)


void math_convolve(const float * input, const int input_len, const float * kern, const int kern_len, float * output,const int output_len)
{
	// 初始化为0
    int offset = 0;
	float *tmp = new float[input_len + kern_len - 1];
	std::cout << __func__ << __LINE__ << "\t input_len=" << input_len << "\t kern_len=" << kern_len << "\t output_len=" << output_len << std::endl;
	for (int i = 0; i < input_len + kern_len - 1; i++)
	{
		tmp[i] = 0;
	}
	//input 4 3 2 1
	// kern 3 2 1 --> 1 2 3
	// 从[0,input_len]的卷积结果
#if 1 == DEBUG_RORATE
	for (int i = 0; i < input_len; i++)
	{
		int k = i;
		for (int j = 0; j < kern_len; j++)
		{
			tmp[i] += input[k] * kern[kern_len - 1 - j];
			k--;
			if (k==-1)
			{
				break;
			}
		}
	}
	//[input_len+1,input_len + kern_len - 1]的卷积结果
	for (int i = 0; i < kern_len - 1; i++)
	{
		int k = 0;
		for (int j = i; j < kern_len - 1; j++)
		{
			tmp[input_len + i] += input[input_len - 1 - k] * kern[kern_len - 1 - 1 - j];
			k++;
		}
	}
	
#else
	for (int i = 0; i < input_len; i++)
	{
		int k = i;
		for (int j = 0; j < kern_len; j++)
		{
			tmp[i] += input[k] * kern[j];
			k--;
			if (k==-1)
			{
				break;
			}
		}
	}
	//[input_len+1,input_len + kern_len - 1]的卷积结果
	for (int i = 0; i < kern_len - 1; i++)
	{
		int k = 0;
		for (int j = i; j < kern_len - 1; j++)
		{
			tmp[input_len + i] += input[input_len - 1 - k] * kern[1 + j];

			k++;
		}
	}
#endif	
	if (output_len== input_len + kern_len - 1)
	{
		std::cout << "line:" << __LINE__ << "\t expect result : 12      17      16      10      4       1" << std::endl;
	    std::cout << "line:" << __LINE__ << "\t full mode!" << std::endl;
		for (int i = 0; i < output_len; i++)
		{
			output[i] = tmp[i];
		}
	}
    else if (output_len==input_len)
	{
		std::cout << "line:" << __LINE__ << "\t expect result : 17      16      10      4" << std::endl;
	    std::cout << "line:" << __LINE__ << "\t same mode!" << std::endl;
		offset = int((kern_len - 1) / 2);
		for (int i = 0; i < output_len; i++)
		{
			output[i] = tmp[i + offset];
		}
	}
	else if (output_len == input_len - kern_len +1)
	{
		std::cout << "line:" << __LINE__ << "\t expect result : 16      10"  << std::endl;
	    std::cout << "line:" << __LINE__ << "\t valid mode!" << std::endl;
		offset = kern_len - 1;
		for (int i = 0; i < output_len; i++)
		{
			output[i] = tmp[i + offset];
		}
	}
}

int cpu_onedimconvolution(void)
{
	int input_len = 8;
	int kern_len = 3;
	int out_len = 0;
	int tmp = 0;
	float input[input_len];
	float kern[kern_len];
	float *out = new float[input_len + kern_len - 1];//3-valid,9-same,15-full
	for (int i = 0; i < input_len; i++)
	{
	    input[i] = input_len - i;
	}
	for (int i = 0; i < kern_len; i++)
	{
	    kern[i] = 1;//kern_len - i;
	}
	
	std::cout << "\t input:" << std::endl;
	for (int i = 0; i < input_len; i++)
	{
	    std::cout << "\t" << input[i];
	}
	std::cout << std::endl;
	std::cout << "\t kern:" << std::endl;
	for (int i = 0; i < kern_len; i++)
	{
	    std::cout << "\t" << kern[i];
	}
	std::cout << std::endl;
#if 1 == DEBUG_RORATE
	for (int i = 0; i < kern_len/2; i++)
	{
		tmp = kern[i];
	    kern[i] = kern[kern_len - 1 - i];
		kern[kern_len - 1 - i] = tmp;
	}

	std::cout << "\t DEBUG_RORATE kern:" << std::endl;
	for (int i = 0; i < kern_len; i++)
	{
	    std::cout << "\t" << kern[i];
	}
	std::cout << std::endl;
#endif
	std::cout << "match convolve start" << std::endl;
	out_len = input_len + kern_len - 1;
	math_convolve(input, input_len, kern, kern_len, out, out_len);
	for (int i = 0; i < out_len; i++)
	{
	    std::cout << "\t" << out[i];
	}
	std::cout << std::endl;
	
	out_len = input_len;
	math_convolve(input, input_len, kern, kern_len, out, out_len);
	for (int i = 0; i < out_len; i++)
	{
	    std::cout << "\t" << out[i];
	}
	std::cout << std::endl;
	
	out_len = input_len - kern_len + 1;
	math_convolve(input, input_len, kern, kern_len, out, out_len);
	for (int i = 0; i < out_len; i++)
	{
	    std::cout << "\t" << out[i];
	}
	std::cout << std::endl;
	std::cout << "match convolve end" << std::endl;
	
ERR_DELETE:
	delete[] out;
    return 0;
}
